#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "double_linkedlist.h"

// 初始化头节点
int dlisthead_init(dlisthead_t **mylist, int size)
{
    if (NULL != *mylist)
        return -1;
    
    *mylist = (dlisthead_t *)malloc(sizeof(dlisthead_t));
    if (NULL == *mylist)
        return -1;
    
    (*mylist)->size = size;
    (*mylist)->nmemb = 0;
    (*mylist)->node.prev = &(*mylist)->node;
    (*mylist)->node.next = &(*mylist)->node;

    return 0;
}

int dlist_empty(const dlisthead_t *mylist)
{
	return mylist->node.next == &(mylist->node) && mylist->node.prev == &(mylist->node);
}

// 头插数据
int dlist_insert(dlisthead_t *mylist, const void *data)
{
    dlist_t *new_node = malloc(sizeof(dlist_t));
    if (NULL == new_node)
        return -1;

    new_node->data = malloc(mylist->size);
    if (NULL == new_node->data) {
        free(new_node);
        new_node = NULL;
        return -1;
    }
    memcpy(new_node->data, data, mylist->size);
    
    new_node->next = mylist->node.next;
    new_node->prev = &mylist->node;
    mylist->node.next->prev = new_node;
    mylist->node.next = new_node;
    mylist->nmemb++;

    return 0;
}

// 尾插数据
int dlist_insert_tail(dlisthead_t *mylist, const void *data)
{
    dlist_t *new_node = malloc(sizeof(dlist_t));
    if (NULL == new_node)
        return -1;

    new_node->data = malloc(mylist->size);
    if (NULL == new_node->data) {
        free(new_node);
        new_node = NULL;
        return -1;
    }
    memcpy(new_node->data, data, mylist->size);
    
    new_node->prev = mylist->node.prev;
    new_node->next = &mylist->node;
    mylist->node.prev->next = new_node;
    mylist->node.prev = new_node;
    mylist->nmemb++;

    return 0;
}

static dlist_t *__find_node(const dlisthead_t *mylist, const void *key, int (*cmp)(const     void *data, const void *key))
{
    if (0 == mylist->nmemb)
        return NULL;

    dlist_t *tmp = mylist->node.next;

    while (tmp != &mylist->node) {
        if (0 == cmp(tmp->data, key))
            return tmp;
        tmp = tmp->next;
    }

    return NULL;
    
}

// 查找元素
void *dlist_search(const dlisthead_t *mylist, const void *key, int (*cmp)(const void *data, const void *key))
{
    dlist_t *cur = __find_node(mylist, key, cmp);
    if (NULL == cur)
        return NULL;

    return cur->data;
}

// 删除元素
int dlist_delete(dlisthead_t *mylist, const void *key, int (*cmp)(const void *data, const void *key))
{
    dlist_t *find = __find_node(mylist, key, cmp);
    if (NULL == find)
        return -1;

    find->prev->next = find->next;
    find->next->prev = find->prev;
    find->next = find->prev = find;

    free(find->data);
    find->data = NULL;
    free(find);
    find = NULL;

    mylist->nmemb--;

    return 0;
}

// 删除并回填数据
int dlist_fetch(dlisthead_t *mylist, const void *key, int (*cmp)(const void *data, const void *key), void *data)
{
    dlist_t *find = __find_node(mylist, key, cmp);
    if (NULL == find)
        return -1;

    memcpy(data, find->data, mylist->size);

    find->prev->next = find->next;
    find->next->prev = find->prev;
    find->next = find->prev = find;

    free(find->data);
    find->data = NULL;
    free(find);
    find = NULL;

    mylist->nmemb--;

    return 0;
}

// 遍历链表
void dlist_traval(const dlisthead_t *mylist, void (*pri)(const void *data))
{
    if (0 == mylist->nmemb)
        return;
    dlist_t *cur = mylist->node.next;

    while (cur != &(mylist->node)) {
        pri(cur->data);
        cur = cur->next;
    }
}

static int __always_cmp(const void *data, const void *key)
{
	return 0;
}

// 销毁链表
void dlist_destroy(dlisthead_t **mylist)
{
    while (!dlist_empty(*mylist)) {
        dlist_delete(*mylist, NULL, __always_cmp);        
    }

    free(*mylist);
    *mylist = NULL;
}


